#include "stdafx.h"

#include "Util.h"
#include "Entity.h"
#include "Reference.h"
using namespace System::Text;
using namespace System::IO;
using namespace System::Runtime::InteropServices; // for class Marshal
using namespace System::Diagnostics;

namespace ManagedAPI
{
	/*
	// static method
	Reference^ Reference::Create(const UdbReference& ref)
	{
		Debug::Assert(ref != nullptr);
		IntPtr entPtr = static_cast<IntPtr>( ref );

		Reference^ result = nullptr;
		if (sRefList->ContainsKey(entPtr))
		{
			result = sRefList[entPtr];
			Debug::Assert(result != nullptr);
		}
		else
		{
			result = gcnew Reference(ref);
			sRefList->Add(entPtr, result);
		}
		return result;
	}
	*/
	Reference::Reference()
	{

	}
	Reference::~Reference()
	{

	}
	Reference::Reference(const UdbReference& ref)
		: mFile(nullptr),
		  mThisEnt(nullptr)
	{
		mLine = udbReferenceLine(ref);
		mColumn = udbReferenceColumn(ref);
		
		UdbEntity entScope = udbReferenceScope(ref);
		mScope = Entity::Create(entScope);

		// file Entities don't reference themselves, hence the pointer is null;
		UdbEntity entFile = udbReferenceFile(ref);
		mFile = Entity::Create(entFile);

		UdbEntity thisEnt = udbReferenceEntity(ref);
		::UdbKind thisEntKind = udbEntityKind(thisEnt);
		char* kindString = udbKindLongname(thisEntKind);
		mKindString = gcnew String(kindString);
		mKind = gcnew ManagedAPI::Kind(thisEntKind);

		// BUG!! Uncomment lines below to show bug!!
//		::UdbKind thiskind = udbReferenceKind(ref);
//		Debug::Assert(thisEntKind == thiskind, "Kind doesn't match"); // compare with the kind found in line 57
		
		mThisEnt = Entity::Create(thisEnt);
	}


	Entity^ Reference::File::get()
	{
		return mFile;
	}
	int Reference::Line::get()
	{
		return mLine;
	}
	int Reference::Column::get()
	{
		return mColumn;
	}
	Entity^ Reference::ThisEntity::get()
	{
		return mThisEnt;
	}
	ManagedAPI::Kind^ Reference::Kind::get()
	{
		return mKind;
	}
	String^ Reference::KindName::get()
	{
		return mKindString;
	}
	Entity^ Reference::Scope::get()
	{
		return mScope;
	}
	String^ Reference::ToString()
	{
		StringBuilder^ sb = gcnew StringBuilder();
		sb->AppendFormat("{0} - {1}({2}) - {3}", mKindString, mFile->NameShort, mLine.ToString(), mThisEnt->NameShort);
		return sb->ToString();
	}
}